<?php
// +----------------------------------------------------------------------
// | sfadmin - Suifeng Administration
// +----------------------------------------------------------------------
// | Copyright (c) 2017-2020 http://suifeng.tech All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: suifeng <1787585212@qq.com>
// +----------------------------------------------------------------------

namespace suifeng\mvc;

final class Hook
{
    /**
     * 已注册的钩子列表。
     *
     * @var array
     */
    protected static $hooks = array();

    /**
     * 注册一个钩子。
     *
     * @param unknown $hook
     * @param unknown $callback
     */
    public static function register($hook, $callback)
    {
        self::$hooks[$hook][] = $callback;

    }

    /**
     * 调用一个钩子。
     *
     * @param unknown $hook
     * @param unknown $args
     * @return NULL|mixed|unknown
     */
    public static function invoke($hook, &$args = null)
    {
        if (empty(self::$hooks[$hook])) {
            return null;
        }

        $result = null;

        foreach (self::$hooks[$hook] as $callback) {
            if ($callback instanceof \Closure) {
                $return = call_user_func_array($callback, [ & $args ]);
            } elseif (is_array($callback)) {
                list($class, $method) = $callback;
                if (is_object($class)) {
                    $return = $class->$method($args);
                } else {
                    $return = (new $class())->$method($args);
                }
            } elseif (is_object($callback)) {
                $return = $class->$hook($args);
            } elseif (strpos($class, '::')) {
                $return = call_user_func_array($class, [ & $args ]);
            } else {
                $obj = new $callback();
                $method = is_callable([$obj, $hook]) ? $hook : 'run';
                $return = $obj->$method($args);
            }

            if ($return !== null) {
                $result[] = $return;
            }
        }

        return $result;
    }
}